const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const ApplicationSchema = new Schema({
  userID: Number,
  deviceID: String,
  deviceModel: String,
  duration: Number,
  applyTime: { type: Date, default: Date.now },
  isAvailable: { type: Boolean, default: true },
}, { timestamps: true });

ApplicationSchema.statics.getDevices = function* getDevices(userID, isAvailable) {
  const info = yield this.find({ userID, isAvailable }, { userID: 0, createdAt: 0, updatedAt: 0, _id: 0 }).exec();
  if (info.length === 0) {
    return [];
  }

  const discards = [];
  for (let i = 0; i < info.length; i++) {
    if (Date.now() - info[i].applyTime > info[i].duration * 60 * 1000) {
      yield info[i].update({ isAvailable: false });
      discards.push(i);
    }
  }
  for (let index of discards) {
    info.splice(index, 1);
  }
  return info;
};

ApplicationSchema.statics.releaseDevice = function* releaseDevice(deviceID, userID) {
  if (userID) {
    yield this.update({ deviceID, userID, isAvailable: true }, { isAvailable: false });
  } else {
    yield this.update({ deviceID, isAvailable: true }, { isAvailable: false });
  }
};

ApplicationSchema.statics.isAvailable = function* isAvailable(deviceID, userID) {
  const info = yield this.findOne({ deviceID, userID, isAvailable: true }).exec();
  if (!info) {
    throw new Error('Device not found');
  }

  if (!info.isAvailable) {
    throw new Error('Device is not available');
  }

  if (Date.now() - info.applyTime > info.duration * 60 * 1000) {
    yield info.update({ isAvailable: false });
    throw new Error('Device is timeout');
  }
};

ApplicationSchema.statics.isAllowApply = function* isAllowApply(userID) {
  const info = yield this.findOne({ userID, isAvailable: true}).exec();
  if (!info) {
    return;
  }
  throw new Error('您正在使用其他设备，请先断开后使用此设备');
};

ApplicationSchema.statics.isUsed = function* isUsed(deviceID, isAvailable, userID) {
  const info = yield this.find({ deviceID, isAvailable }).sort({ applyTime: -1 }).exec();
  if (info.length === 0) {
    return;
  }

  const infoJson = info[0].toJSON();
  if (Date.now() - infoJson.applyTime > infoJson.duration * 60 * 1000) {
    yield info[0].update({ isAvailable: false });
    return;
  }
  if (infoJson.userID === userID) {
    throw new Error('Please don\'t apply duplicate');
  }
  throw new Error('Device has being used');
};

// Model creation
mongoose.model('Application', ApplicationSchema);
